package com.tianji.learning.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.remark.RemarkClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.page.ReplyPageQuery;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author ffk
 * @since 2024-06-25
 */
@RequiredArgsConstructor
@Service
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {

    private final IInteractionQuestionService questionService;
    private final UserClient userClient;
    private final RemarkClient remarkClient;
    /**
     * 用户新增回答或评论
     * @param replyDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveReply(ReplyDTO replyDTO) {
        //1.判断参数是否合法
        if (ObjectUtil.isEmpty(replyDTO)) {
            throw new BizIllegalException("添加回答或评论参数不合法");
        }
        //2.获取用户id,添加表格
        Long userId = UserContext.getUser();
        InteractionReply interactionReply = BeanUtils.copyBean(replyDTO, InteractionReply.class);
        interactionReply.setUserId(userId);
        save(interactionReply);
        //3.1判断是否是回答,如果是,需要修改问题最近一下回答的id
        //表示是回答问题,不是回答评论或者回答回答
        if (ObjectUtil.isEmpty(replyDTO.getAnswerId()) && ObjectUtil.isEmpty(replyDTO.getTargetReplyId())) {
            boolean update = questionService.lambdaUpdate()
                    .eq(InteractionQuestion::getId, replyDTO.getQuestionId())
                    .set(InteractionQuestion::getLatestAnswerId, interactionReply.getId())
                    .setSql("answer_times = answer_times + 1")
                    .update();
            if (!update) {
                throw new DbException("修改问题最近回答id失败");
            }
        } else {
            //3.2.如果是回答回答或者回答评论,上一级的回答数要加1
            //如果answerId和targetReplyId相等,说明是评论回答,上一级的回答数要加1
            if (replyDTO.getAnswerId().equals(replyDTO.getTargetReplyId())) {
                boolean update = this.lambdaUpdate().eq(InteractionReply::getId, replyDTO.getAnswerId())
                        .setSql("reply_times = reply_times + 1")
                        .update();
                if (!update) {
                    throw new DbException("修改问题最近回答id失败");
                }
            } else {
                //如果不相等,表示是回复评论,评论加1,算了前端有问题,跟着傻子写得了
                boolean update1 = this.lambdaUpdate().eq(InteractionReply::getId, replyDTO.getAnswerId())
                        .setSql("reply_times = reply_times + 1")
                        .update();
                if (!update1) {
                    throw new DbException("修改问题最近回答id失败");
                }
                boolean update2 = this.lambdaUpdate().eq(InteractionReply::getId, replyDTO.getTargetReplyId())
                        .setSql("reply_times = reply_times + 1")
                        .update();
                if (!update2) {
                    throw new DbException("修改问题最近评论id失败");
                }
            }
        }
        //4.判断是否是学生回答,如果不是,需要修改问题状态为未查看
        if (!replyDTO.getIsStudent()) {
            boolean update1 = questionService.lambdaUpdate().eq(InteractionQuestion::getId, replyDTO.getQuestionId())
                    .set(InteractionQuestion::getStatus, QuestionStatus.UN_CHECK)
                    .update();
            if (!update1) {
                throw new DbException("修改问题状态失败");
            }
        }
    }

    /**
     * 用户端端分页查询回答或者评论列表
     */
    @Override
    public PageDTO<ReplyVO> userPageQueryReply(ReplyPageQuery replyPageQuery) {
        //1.先判断参数是否正确
        if (replyPageQuery.getQuestionId() == null && replyPageQuery.getAnswerId() == null) {
            return PageDTO.empty(0L, 0L);
        }

        PageDTO<ReplyVO> pageVo = PageDTO.empty(0L, 0L);

        //这个就是问题分页
        if (replyPageQuery.getQuestionId() != null && replyPageQuery.getAnswerId() == null) {
            pageVo = questionQuery(replyPageQuery);
        }

        if (replyPageQuery.getQuestionId() == null && replyPageQuery.getAnswerId() != null) {
            pageVo = answerQuery(replyPageQuery);
        }
        return pageVo;
    }

    /**
     * 用户端-分页查询评论列表
     * @param replyPageQuery
     * @return
     */
    private PageDTO<ReplyVO> answerQuery(ReplyPageQuery replyPageQuery) {
        Page<InteractionReply> replyPage = this.lambdaQuery()
                .eq(InteractionReply::getAnswerId, replyPageQuery.getAnswerId())
                .eq(InteractionReply::getHidden, false)
                .page(replyPageQuery.toMpPage("liked_times", false));
        List<InteractionReply> records = replyPage.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return PageDTO.empty(replyPage);
        }
        Set<Long> targetUserIds = new HashSet<>();
        Set<Long> replyIds = new HashSet<>();
        Set<Long> questionIds = new HashSet<>();
        Set<Long> bizIds=new HashSet<>();
        for (InteractionReply record : records) {
            if (!record.getAnonymity()) {
                questionIds.add(record.getUserId());
            }
            replyIds.add(record.getTargetUserId());
            bizIds.add(record.getId());//点赞ids
        }
        List<InteractionReply> replyList = lambdaQuery().in(InteractionReply::getUserId, replyIds).list();
        for (InteractionReply interactionReply : replyList) {
            if (!interactionReply.getAnonymity()) {
                targetUserIds.add(interactionReply.getUserId());
            }
        }

        //点赞状态查询
        Set<Long> likedStatus = remarkClient.queryLikedStatus(bizIds);


        List<UserDTO> questionId = userClient.queryUserByIds(questionIds);
        Map<Long, UserDTO> collect = questionId.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
        List<UserDTO> replyId = userClient.queryUserByIds(targetUserIds);
        Map<Long, UserDTO> collect1 = replyId.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
        List<ReplyVO> voList = new ArrayList<>();
        for (InteractionReply record : records) {
            ReplyVO replyVO = BeanUtils.copyBean(record, ReplyVO.class);
            if (collect.get(record.getUserId()) != null) {
                if (!record.getAnonymity()) {
                    replyVO.setUserName(collect.get(record.getUserId()).getName());
                    replyVO.setUserIcon(collect.get(record.getUserId()).getIcon());
                }
            }
            if (collect1.get(record.getTargetUserId()) != null) {
                replyVO.setTargetUserName(collect1.get(record.getTargetUserId()).getName());
            }
            voList.add(replyVO);
            //设置点赞
            replyVO.setLiked(likedStatus.contains(record.getId()));
        }
        return PageDTO.of(replyPage, voList);
    }

    /**
     * 用户端-分页查询回答列表
     * @param replyPageQuery
     * @return
     */
    private PageDTO<ReplyVO> questionQuery(ReplyPageQuery replyPageQuery) {
        Page<InteractionReply> questionPage = this.lambdaQuery()
                .eq(InteractionReply::getQuestionId, replyPageQuery.getQuestionId())
                .eq(InteractionReply::getHidden, false)
                .page(replyPageQuery.toMpPage("liked_times", false));
        //如果是空的话,直接返回
        List<InteractionReply> records = questionPage.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return PageDTO.empty(questionPage);
        }
        Set<Long> questionIds = new HashSet<>();
        Set<Long> bizIds=new HashSet<>();
        //如果不是匿名,添加到集合中
        for (InteractionReply record : records) {
            if (!record.getAnonymity()) {
                questionIds.add(record.getUserId());
            }
            bizIds.add(record.getId());
        }


        //点赞状态查询
        Set<Long> likedStatus = remarkClient.queryLikedStatus(bizIds);

        List<UserDTO> queryQuestionByIds = userClient.queryUserByIds(questionIds);
        Map<Long, UserDTO> collect = queryQuestionByIds.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
        List<ReplyVO> voList = new ArrayList<>();
        for (InteractionReply record : records) {
            UserDTO userInfo = collect.get(record.getUserId());
            ReplyVO replyVO = BeanUtils.copyBean(record, ReplyVO.class);
            if (ObjectUtil.isNotEmpty(userInfo)) {
                if (!record.getAnonymity()) {
                    replyVO.setUserName(userInfo.getName());
                    replyVO.setUserIcon(userInfo.getIcon());
                }
            }

            if(ObjectUtils.isNotEmpty(likedStatus)){
                replyVO.setLiked(likedStatus.contains(record.getId()));
            }
            voList.add(replyVO);
        }
        return PageDTO.of(questionPage, voList);
    }

    /**
     * 管理端-分页查询互动回答或者评论列表
     * 在问答列表，都某个问题点击查看问题，传问题id questionId，查出来回答列表
     * 在回答列表，对某个回答点击查看更多，传回答id answerId，查出来评论列表
     * @param query
     * @return
     */
    @Override
    public PageDTO<ReplyVO> adminPageQueryReply(ReplyPageQuery query) {
        //都为空，返回空
        if(ObjectUtils.isEmpty(query.getQuestionId()) && ObjectUtils.isEmpty(query.getAnswerId())){
            return PageDTO.empty(0L,0L);
        }

        PageDTO<ReplyVO> pageVo = PageDTO.empty(0L,0L);

        //只查问题列表
        if(ObjectUtils.isNotEmpty(query.getQuestionId()) && ObjectUtils.isEmpty(query.getAnswerId())){
            pageVo=  justQueryAnswerList(query);
        }

        //只查评论列表
        if( ObjectUtils.isNotEmpty(query.getAnswerId()) && ObjectUtils.isEmpty(query.getQuestionId())){
            pageVo=  justQueryCommentList(query);
        }

        return pageVo;

    }

    //查某个问题的回答列表
    private PageDTO<ReplyVO> justQueryAnswerList(ReplyPageQuery query) {
        //根据questionId查出来它的回答列表
        Page<InteractionReply> pageAnswerResult = this.lambdaQuery()
                .eq(InteractionReply::getQuestionId, query.getQuestionId())
                .orderByDesc(InteractionReply::getLikedTimes)
                .orderByDesc(InteractionReply::getCreateTime)
                .page(query.toMpPage());

        //回答列表
        List<InteractionReply> answerRecordsList = pageAnswerResult.getRecords();

        //根据回答者id远程调用查用户信息
        Set<Long> userIds = answerRecordsList.stream().map(InteractionReply::getUserId).collect(Collectors.toSet());
        List<UserDTO> userInfo = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userMap=new HashMap<>();
        if(ObjectUtils.isNotEmpty(userInfo)){
            userMap = userInfo.stream().collect(Collectors.toMap(UserDTO::getId, userDTO -> userDTO));
        }

        List<ReplyVO> answerVoList=new ArrayList<>();
        for (InteractionReply currentReply : answerRecordsList) {
            ReplyVO replyVO = BeanUtils.copyBean(currentReply, ReplyVO.class);

            Long userId = currentReply.getUserId();
            UserDTO userDTO = userMap.get(userId);

            replyVO.setUserName(userDTO.getName());
            replyVO.setUserIcon(userDTO.getIcon());
            replyVO.setUserType(userDTO.getType());
            answerVoList.add(replyVO);
        }

        return PageDTO.of(pageAnswerResult,answerVoList);
    }


    //查某个回答的评论列表 userid 回复 targetuserid
    private PageDTO<ReplyVO> justQueryCommentList(ReplyPageQuery query) {
        Page<InteractionReply> pageCommentResult = this.lambdaQuery()
                .eq(InteractionReply::getAnswerId, query.getAnswerId())
                .orderByDesc(InteractionReply::getLikedTimes)
                .orderByDesc(InteractionReply::getCreateTime)
                .page(query.toMpPage());

        //评论的数据集合
        List<InteractionReply> commentRecordsList = pageCommentResult.getRecords();
        Set<Long> allIds=new HashSet<>();
        // Map<Long, Long> idsMap=new HashMap<>();
        if(ObjectUtils.isNotEmpty(commentRecordsList)){

            for (InteractionReply interactionReply : commentRecordsList) {
                allIds.add(interactionReply.getUserId());
                allIds.add(interactionReply.getTargetUserId());
                //  idsMap.put(interactionReply.getUserId(),interactionReply.getTargetUserId());
            }
        }

        List<UserDTO> allinfos = userClient.queryUserByIds(allIds);
        Map<Long, UserDTO> allUserMap=new HashMap<>();
        if(ObjectUtils.isNotEmpty(allinfos)){
            allUserMap=allinfos.stream().collect(Collectors.toMap(UserDTO::getId, userDTO -> userDTO));
        }

        List<ReplyVO> commentVoList=new ArrayList<>();
        for (InteractionReply nowReply : commentRecordsList) {
            ReplyVO replyVO = BeanUtils.copyBean(nowReply, ReplyVO.class);
            Long userId = nowReply.getUserId();
            UserDTO userDTO = allUserMap.get(userId);
            replyVO.setUserName(userDTO.getName());
            replyVO.setUserIcon(userDTO.getIcon());
            replyVO.setUserType(userDTO.getType());
            replyVO.setTargetUserName(allUserMap.get(nowReply.getTargetUserId()).getName());
            commentVoList.add(replyVO);
        }
        return PageDTO.of(pageCommentResult,commentVoList);
    }


    /**
     * 管理端-根据id查询评论
     * @param id
     * @return
     */
    @Override
    public ReplyVO adminQueryById(Long id) {
        InteractionReply one = this.lambdaQuery()
                .eq(InteractionReply::getId, id).one();
        ReplyVO replyVO = BeanUtils.copyBean(one, ReplyVO.class);
        //补充数据
        UserDTO userDTO = userClient.queryUserById(one.getUserId());
        UserDTO userDTO1 = userClient.queryUserById(one.getTargetUserId());

        if(userDTO!=null && userDTO1!=null){
            replyVO.setUserName(userDTO.getName());
            replyVO.setUserType(userDTO.getType());
            replyVO.setUserIcon(userDTO.getIcon());
            replyVO.setTargetUserName(userDTO1.getName());
        }
        return replyVO;
    }

    /**
     * 管理端隐藏或者显示评论，如果隐藏的是回答，则回答下的评论也要隐藏
     * @param id replyid
     * @param hidden
     */
    @Override
    public void updateAdminReplyHidden(Long id, Boolean hidden) {
        //先根据id查出来
        InteractionReply one = this.lambdaQuery()
                .eq(InteractionReply::getId, id)
                .one();

        if(ObjectUtils.isNotEmpty(one) && one.getAnswerId()==0 ){
            //回答，把该回答下的评论改了
            boolean update1 = this.lambdaUpdate()
                    .set(hidden != null, InteractionReply::getHidden, hidden)
                    .eq(InteractionReply::getAnswerId, id)
                    .update();
            //回答自己也更新
            boolean update2 = this.lambdaUpdate()
                    .set(hidden != null, InteractionReply::getHidden, hidden)
                    .eq(InteractionReply::getId, id)
                    .update();

            if(!update1 || !update2){
                throw new BadRequestException("回答更新失败");
            }
        }

        if(ObjectUtils.isNotEmpty(one) && one.getAnswerId()!=0){
            // TODO: 2024/6/27 有bug
            //评论
            boolean result = this.lambdaUpdate()
                    .set(hidden != null, InteractionReply::getHidden, hidden)
                    .eq(InteractionReply::getId, id)
                    .update();
            if(!result){
                throw new BadRequestException("评论更新失败");
            }
        }
    }
}
